// 代码整理
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

/**
 *
 *
 * @class MyPromise
 */
class MyPromise {
    constructor(executor) {
        try {
            executor(this.resolve, this.reject)    
        } catch (error) {
            this.reject(error)   
        }
    }
    status = PENDING

    value = null
    reason = null

    onFulfilledCallbacks = []
    onRejectedCallbacks = []

    resolve = (value) => {
        if (this.status === PENDING) {
            this.status = FULFILLED
            this.value = value
            while(this.onFulfilledCallbacks.length) {
                this.onFulfilledCallbacks.shift()(value)
            }
        }
    }
    reject = (reason) => {
        if (this.status === PENDING) {
            this.status = REJECTED
            this.reason = reason
            while(this.onRejectedCallbacks.length) {
                this.onRejectedCallbacks.shift()(reason)
            }
        }
    }

    then = (onFulfilled, onRejected) => {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
        onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason}
        const p2 = new MyPromise((resolve, reject) => {
            const fulfilledQueueMicrotask = () => {
                queueMicrotask(() => {
                    try {
                        const x = onFulfilled(this.value)
                        resolvePromise(p2, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                })
            }
            const rejectedQueueMicrotask = () => {
                queueMicrotask(() => {
                    try {
                        const x = onRejected(this.reason)
                        resolvePromise(p2, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                })
            }
            if (this.status === FULFILLED) {
                fulfilledQueueMicrotask()
            }
            else if (this.status === REJECTED) {
                rejectedQueueMicrotask()
            }
            else {
                this.onFulfilledCallbacks.push(fulfilledQueueMicrotask)
                this.onRejectedCallbacks.push(rejectedQueueMicrotask)
            }
        })
        return p2
    }
    static resolve (params) {
        if (params instanceof MyPromise) {
            return params
        }
        return new MyPromise((resolve, reject) => {
            resolve(params)
        })
    }
    static reject (err) {
        return new MyPromise((resolve, reject) => {
            reject(err)
        })
    }
}
function resolvePromise(p2, x, resolve, reject) {
    if (x instanceof MyPromise) {
        if (x === p2) {
            return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
        } else {
            x.then(resolve, reject)
        }
    } else {
        resolve(x)
    }
}

MyPromise.resolve().then(() => {
    console.log(0);
    return MyPromise.resolve(4);
}).then((res) => {
    console.log(res)
})

MyPromise.resolve().then(() => {
    console.log(1);
}).then(() => {
    console.log(2);
}).then(() => {
    console.log(3);
}).then(() => {
    console.log(5);
}).then(() =>{
    console.log(6);
})

  